TemplateCompiler.php

<?php

namespace Phad\Test\Compilation;

class TemplateCompiler extends \Phad\Tester {

    public function testIfs(){
        $c2 = new \Phad\TemplateCompiler();
        
        $template = <<<'PHP'
        /* @@if1.start.a */
        if ($a)echo $a;
        /* @@end.a */
        /* @@if1.start.b */
        if ($b)echo $b;
        /* @@end.b */
        /* @@if1.start.c */
        if ($c)echo $c;
        /* @@end.c */
        /* @@if1.start.d */
        if ($d)echo $d;
        /* @@end.d */
        /* @@else1 */echo 'last_one';
        PHP;

        $template_original = $template;
            
            // so i need the start/end feature AND the if feature


        $this->test('all ifs');

        $code = [
            'a'=>true,
            'b'=>true,
            'c'=>true,  
            'd'=>true,
        ];

        $c2->precompile_ifs($template, $code);

        // echo "\n\n\n-----------\n\n";
        // var_dump($template);
        // print_r($code);
        // exit;

        $this->compare(
            ['a','b','c','d','__ifs1_0','__ifs1_1','__ifs1_2','__ifs1_3', 'else1'],
            array_keys($code)
        );

        $this->compare('else', $code['__ifs1_1']);

        $template_args = $c2->get_template_args($template, $code);
        $this->compare('/* @@__ifs1_0 */', $template_args['__ifs1_0']);

        $compiled = $c2->fill_template($template, $template_args, $code);

        $this->compare(
            <<<'PHP'
            if ($a)echo $a;


            elseif ($b)echo $b;


            elseif ($c)echo $c;


            elseif ($d)echo $d;

            else echo 'last_one';
            PHP,
            $compiled
        );

        




        $this->test('remove SOME ifs');


        $template = $template_original;
        $code2 = [
            'b'=>true,
            'd'=>true,
        ];
        $code = $code2;
        $c2->precompile_ifs($template, $code2);

        $this->compare(
            ['b','d','__ifs1_1','__ifs1_3', 'else1'],
            array_keys($code2)
        );

        $this->compare('', $code2['__ifs1_1']);
        $this->compare('else', $code2['__ifs1_3']);



        // return;
        $template_args = $c2->get_template_args($template, $code2);
        $this->compare('/* @@__ifs1_1 */', $template_args['__ifs1_1']);
        $this->compare('/* @@__ifs1_2 */', $template_args['__ifs1_2']);
        // $indent = '    ';

        $code = [
            'big'=>true,
        ];

        $compiled = $c2->fill_template($template, $template_args, $code2);

        $this->compare(
            <<<'PHP'
            if ($b)echo $b;



            elseif ($d)echo $d;

            else echo 'last_one';
            PHP,
            $compiled
        );


        $this->test('no ifs');

        $template = $template_original;
        $code = [];
        $c2->precompile_ifs($template, $code);
        $params = $c2->get_template_args($template, $code);
        $compiled = $c2->fill_template($template,$template_args, $code);

        // echo $compiled;

        $this->compare("echo 'last_one';", $compiled);
    }

    public function testStartEnd(){
        $c2 = new \Phad\TemplateCompiler();
        $template = <<<'PHP'
        /* @@start.big */
        $sum = 60;
        /* @@end.big */
        /* @@start.small */
        $sum = 1;
        /* @@end.small */
        echo $sum;
        PHP;


        $template_fillers = [
            'big'=>true,
        ];

        $template_args = $c2->get_template_args($template, $template_fillers);
        // $indent = '    ';
        $this->compare(
            ['big'=>"/* @@start.big */\n\$sum = 60;\n/* @@end.big */",
            'small'=>"/* @@start.small */\n\$sum = 1;\n/* @@end.small */"],
            $template_args,
        );


        $compiled = $c2->fill_template($template, $template_args, $template_fillers);

        $expect = <<<'PHP'
        $sum = 60;


        echo $sum;
        PHP;

        $this->compare($expect, $compiled);

        ob_start();
        eval($compiled);
        $output = ob_get_clean();

        $this->compare("60",$output);
    }

    /**
     * @test @$$Param format
     */
    public function testTemplateArgs2(){
        $c2 = new \Phad\TemplateCompiler();
        $template = <<<'PHP'
            $sum = 6;
            function increment($v){return $v+1;}
            @$$Param = increment(@$$Param);
            echo @$$Param;
        PHP;

        $template_args = $c2->get_template_args($template, $code);
        $this->compare(['Param'=>'@$$Param'], 
            $template_args
        );

        $code = [
            'Param' => '$sum'
        ];

        $compiled = $c2->fill_template($template, $template_args, $code);

        $expect = <<<'PHP'
            $sum = 6;
            function increment($v){return $v+1;}
            $sum = increment($sum);
            echo $sum;
        PHP;

        $this->compare($expect, $compiled);

        ob_start();
        eval($compiled);
        $output = ob_get_clean();

        $this->compare("7",$output);
    }

    /**
     * @test /* @@param *\/ format
     * @test params are extracted from template code
     * @test placeholders are replaced by given code
     * @test placeholders are removed if no code given for their param
     * @test compiled code `eval`s with intended output
     */ 
    public function testTemplateArgs(){
        $c2 = new \Phad\TemplateCompiler();
        $template = <<<PHP
            echo "one";
            /* @@two */
            echo "three";
            /* @@four */
            /* @@nope */
        PHP;

        $template_args = $c2->get_template_args($template, $whatever);
        $this->compare(
            ['two'=>'/* @@two */', 
            'four'=>'/* @@four */',
            'nope'=> '/* @@nope */',
            ], $template_args);


        $code = [
            'two'=>'echo "two";',
            'four'=>'echo "four";',
        ];

        $compiled = $c2->fill_template($template, $template_args, $code);

        $expect = <<<PHP
            echo "one";
            echo "two";
            echo "three";
            echo "four";
        PHP;

        $this->compare($expect, $compiled);

        ob_start();
        eval($compiled);
        $output = ob_get_clean();

        $this->compare(
            "onetwothreefour",
            $output
        );
    }

}